//
//  User.swift
//  App
//
//  Created by melvyn on 2018/8/18.
//

import Vapor
import Fluent

struct User: Codable {
    
    var id: Int?
    var nickname: String?
    var username: String
    var password: String
    var age: UInt?
    var sex: Int?
    var avatar: String?
    var level: Int? = 1
}
extension User {
    var lives: Children<User, LiveStream> {
        return children(\.uid)
    }
    
    var comments: Children<User, Comment> {
        return children(\.uid)
    }
}

extension User: Entity {}
extension User: Migration {}
extension User: Content {}
extension User: Parameter {}

import Authentication
extension User: BasicAuthenticatable {
    static let usernameKey: UsernameKey = \User.username
    static let passwordKey: PasswordKey = \User.password
}

extension User: TokenAuthenticatable {
    typealias TokenType = Token
}


extension User {
    struct Public: Codable {
        var id: Int?
        var avatar: String?
        var level: Int?
        var nickname: String?
        var username: String
        var age: UInt?
        var sex: Int?
        
        init(_ user: User) {
            id = user.id
            nickname = user.nickname
            avatar = user.avatar
            level = user.level
            username = user.username
            age = user.age
            sex = user.sex
        }
    }
}

extension User.Public: Entity {
    static let entity = User.entity
}
extension User.Public: Content {}
extension User.Public: Parameter {}

extension User {
    
    struct FormData: Codable {
        var nickname: String?
        var username: String?
        var password: String?
        var age: UInt?
        var sex: Int?
        var metadata: Data?
    }
    
    // create new user from form data
    init(formData: FormData) throws {
        username = formData.username!
        password = try BCrypt.hash(formData.password!)
        nickname = formData.nickname ?? username
        age = formData.age
        sex = formData.sex
        avatar = try? Utility.default.save(formData.metadata).0
        level = 1 //default level value
    }
    
    // update a existed user from form data
    func update(with: FormData) -> User {
        var newValue = self
        newValue.nickname = with.nickname ?? nickname
        newValue.username = with.username ?? username
        newValue.password = with.password ?? password
        newValue.age = with.age ?? age
        newValue.sex = with.sex ?? sex
        
        guard let metadata = with.metadata else { return newValue }
        
        newValue.avatar = try? Utility.default.save(metadata, name: id!, destination: avatarURL).0
        return newValue
    }
}

